package com.hsj.rabbitmq.config;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import pojo.User;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * @author:Teacher黄
 * @date:Created at 2020/01/04
 */
@Configuration
public class RabbitConfig {


    /**
     * mq模板对象
     * @param connectionFactory
     * @return
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMandatory(true);

        /**
         * 消息 => exchange 的回调
         * 如果消息没有到exchange,则confirm回调,ack=false
         * 如果消息到达exchange,则confirm回调,ack=true
         */
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             *
             * @param correlationData
             * @param ack : 确认是否道道exchange
             * @param cuse : 原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cuse) {
                if(ack){
                    // 消息成功到达exchange 可以做状态改变处理
                    System.out.println("消息投递exchange成功");
                }else{
                    System.out.println("消息投递exchange失败:"+cuse);
                    // correlationData 中获取返回的消息, 在发送消息的时候可以设置为redis中的key/下标
                    // 如果投递失败可以继续从redis中获取消息 继续投递
                    Message returnedMessage = correlationData.getReturnedMessage();
                    String s = new String(returnedMessage.getBody());
                    System.out.println("返回的消息:"+s);
                }
            }
        });

        /**
         * exchange到queue成功,则不回调return
         * exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
         */
        // 回调函数 return
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /**
             * 返回消息的方法
             * @param message : 发送的消息
             * @param replyCode : 状态码
             * @param replyText : 状态内容
             * @param exchange : 交换机
             * @param routingKey : 路由键
             */

            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                // 可以进行消息的转存
                System.out.println("消息丢失:");
                System.out.println("状态码:"+replyCode);
                System.out.println("状态信息:"+replyText);
                System.out.println("交换机:"+exchange);
                System.out.println("路由键:"+routingKey);
                try {
                    // 可以将消息转换成具体的业务的对象
                    byte[] body = message.getBody();
                    // 利用对象流转对象
                    ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(body));
                    User user = (User) objectInputStream.readObject();
                    System.out.println("传递的对象"+user);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }


            }
        });

        return rabbitTemplate;
    }


}
